;;; ac-include-files.el --- Autocompletion source for c/c++ header files
;;
;; Filename: ac-include-files.el
;; Description: Autocompletion source for c/c++ header files
;; Author: Yiping Qi
;; Email: qiyiping@gmail.com
;; Maintainer: Yiping Qi
;; Created: Sun Oct 16 13:25:38 2011
;; Version: 0.1
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation; either version 3, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program; see the file COPYING.  If not, write to
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
;; Floor, Boston, MA 02110-1301, USA.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; Commentary:
;;
;; Put this file into load-path'ed directory, and byte compile it if
;; desired.  And put the following expression into your ~/.emacs.
;;
;; (require 'ac-include-filename)
;; (setq 'ac-include-dir (list
;;     			  "path-to-the-include-dir-end-with-/"))
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; code:

(defvar ac-include-dir nil
  "c/c++ include directories")

(defun ac-filename-in-dir (include-dir prefix)
  (let ((dir (file-name-directory (concat include-dir prefix)))
	(paths nil)
	(files nil))
    (if (file-directory-p dir)
	(setq paths (directory-files dir t)))
    (dolist (path paths)
      (push (substring path (length include-dir)) files))
    files))


(defun ac-include-filename-candidate ()
  (let ((filenames nil)
	(subpath (buffer-substring-no-properties (ac-include-prefix) (point))))
    (dolist (dir ac-include-dir)
      (if (not filenames)
	  (setq filenames (ac-filename-in-dir dir subpath))
	(nconc filenames (ac-filename-in-dir dir subpath))))
    (sort filenames 'string-lessp)))

(defun ac-include-prefix ()
  (save-excursion
    (let ((current-point (point))
	  (begin-point nil))
      (beginning-of-line)
      (if (looking-at "#include *[\"<]")
	  (progn
	    (goto-char current-point)
	    (if (looking-back "[^\"<]+" nil t)
		(setq begin-point (match-beginning 0)))))
      begin-point)))

(defvar ac-source-include-filename
  '((symbol . "i")
    (prefix . ac-include-prefix)
    (candidates . ac-include-filename-candidate)))

(add-hook 'c-mode-common-hook
	  '(lambda ()
	     (setq ac-sources (append '(ac-source-include-filename) ac-sources))))

(provide 'ac-include-filename)